<script lang="jsx">
	import { tableProps } from 'ant-design-vue/es/table/Table.js'
	import { get } from 'lodash-es'
	import draggable from 'vuedraggable-es'
	import columnSetting from './columnSetting.vue'
	import './index.less'

	/*
		// 参考示例：form-fields配置（用于SearchForm组件）
		:form-fields="[
			{ label: 'PO/项目名称', name: 'poName', span: 6 },
			{ label: 'PO/项目编码', name: 'projectCode', span: 6, advanced: true },
			{ label: '年份', name: 'year', span: 6, advanced: true },
			{ label: '月份', name: 'month', span: 6, advanced: true },
			{ label: '姓名', name: 'userName', span: 6, advanced: true }
		]"
		*/
	export default {
		components: {
			draggable,
			columnSetting
		},
		data() {
			return {
				showOperator: true,
				needTotalList: [],
				selectedRows: [],
				selectedRowKeys: [],
				localLoading: false,
				localDataSource: [],
				localPagination: Object.assign({}, this.pagination),
				isFullscreen: false,
				customSize: this.compSize,
				columnsSetting: [],
				localSettings: {
					rowClassName: this.rowClassName,
					rowClassNameSwitch: Boolean(this.rowClassName)
				},
				uploadLoading: false
			}
		},
		// eslint-disable-next-line vue/order-in-components
		props: Object.assign({}, tableProps(), {
			pageSizeOptions: {
				type: Array,
				default: [10, 20, 30, 40, 50, 100, 200]
			},
			rowKey: {
				type: [String, Function],
				default: 'key'
			},
			data: {
				type: Function,
				required: true
			},
			pageNum: {
				type: Number,
				default: 1
			},
			size: {
				type: String,
				default: '10'
			},
			showSizeChanger: {
				type: Boolean,
				default: true
			},
			compSize: {
				type: String,
				default: 'middle'
			},
			alert: {
				type: [Object, Boolean],
				default: null
			},
			rowSelection: {
				type: Object,
				default: null
			},
			/** @Deprecated */
			showAlertInfo: {
				type: Boolean,
				default: false
			},
			showPagination: {
				type: [String, Boolean],
				default: 'auto'
			},
			/**
			 * enable page URI mode
			 *
			 * e.g:
			 * /users/1
			 * /users/2
			 * /users/3?queryParam=test
			 * ...
			 */
			pageURI: {
				type: Boolean,
				default: false
			},
			extraTool: {
				type: Array,
				default: () => []
			},
			// 配置工具栏
			toolConfig: {
				type: Object,
				default: () => ({
					refresh: false,
					height: false,
					columnSetting: false,
					striped: false
				})
			},
			// 操作按钮配置
			operatorConfig: {
				type: Array,
				default: () => []
			}
			/*
				// 参考示例：operatorConfig配置
				const operatorConfig = computed(() => [
					{
						text: '提交',
						icon: 'fa fa-check',
						onClick: batchCompleteTask,
						disabled: selectedRowKeys.value.length === 0,
						visible: hasPerm('timeSheetTaskComplete')
					},
					{
						text: '提交所有',
						icon: 'fa fa-check-square-o',
						type: 'popconfirm',
						confirmTitle: '将会提交所有的待办数据?',
						okText: '是',
						cancelText: '否',
						onClick: batchAllCompleteTask,
						visible: hasPerm('timeSheetTaskComplete')
					},
					{
						text: '修改详情',
						icon: 'fa fa-edit',
						onClick: () => {
							if (selectedRowKeys.value.length === 1) {
								recordRef.value.onOpen(selectedRowKeys.value[0], 1)
							} else {
								message.warning('请选择一条记录进行修改')
							}
						},
						disabled: selectedRowKeys.value.length !== 1,
						visible: hasPerm('timeSheetTaskRecordEdit')
					},
					{
						text: '删除',
						icon: 'fa fa-trash',
						danger: true,
						onClick: deleteBatchTimeSheetRecord,
						disabled: selectedRowKeys.value.length === 0,
						visible: hasPerm('timeSheetTaskRecordDelete') && actionType.value
					}
				])
				*/
		}),
		watch: {
			'localPagination.current': function (val) {
				this.pageURI &&
					this.$router.push({
						...this.$route,
						name: this.$route.name,
						params: Object.assign({}, this.$route.params, {
							current: val
						})
					})
			},
			pageNum(val) {
				Object.assign(this.localPagination, {
					current: val
				})
			},
			size(val) {
				Object.assign(this.localPagination, {
					size: val
				})
			},
			showSizeChanger(val) {
				Object.assign(this.localPagination, {
					showSizeChanger: val
				})
			},
			columns(v) {
				this.columnsSetting = v
			}
		},
		mounted() {
			const { current } = this.$route.params
			const localPageNum = (this.pageURI && current && parseInt(current)) || this.pageNum
			this.localPagination =
				(['auto', true].includes(this.showPagination) &&
					Object.assign({}, this.localPagination, {
						current: localPageNum,
						size: this.size, //this.compSize, size// 改动
						showSizeChanger: this.showSizeChanger,
						pageSizeOptions: this.pageSizeOptions,
						showTotal: (total, range) => {
							return `${range[0]}-${range[1]} 共 ${total} 条 `
						}
					})) ||
				false
			this.needTotalList = this.initTotalList(this.columns)
			this.loadData()
			this.columnsSetting = this.columns
		},
		methods: {
			/**
			 * 表格重新加载方法
			 * 如果参数为 true, 则强制刷新到第一页
			 * @param bool Boolean
			 */
			refresh(bool = false) {
				bool &&
					(this.localPagination = Object.assign(
						{},
						{
							current: 1,
							size: this.size
						}
					))
				this.loadData()
			},
			/**
			 * 加载数据方法
			 * @param {Object} pagination 分页选项器
			 * @param {Object} filters 过滤条件
			 * @param {Object} sorter 排序条件
			 */
			loadData(pagination, filters, sorter) {
				this.localLoading = true
				const parameter = Object.assign(
					{
						current: (pagination && pagination.current) || (this.showPagination && this.localPagination.current) || this.pageNum,
						size: (pagination && pagination.pageSize) || (this.showPagination && this.localPagination.pageSize) || this.pageSize
					},
					(sorter &&
						sorter.field && {
							sortField: sorter.field
						}) ||
						{},
					(sorter &&
						sorter.order && {
							sortOrder: sorter.order
						}) ||
						{},
					{
						...filters
					}
				)
				const result = this.data(parameter)
				// eslint-disable-next-line
				if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
					result.then((r) => {
						if (r == null) {
							this.localLoading = false
							return
						}
						this.localPagination =
							(this.showPagination &&
								Object.assign({}, this.localPagination, {
									current: r.current, // pageNo, // 返回结果中的当前分页数
									total: r.total, // totalRows, // 返回结果中的总记录数
									showSizeChanger: this.showSizeChanger,
									showTotal: (total, range) => {
										return `${range[0]}-${range[1]} 共 ${total} 条 `
									},
									size: (pagination && pagination.size) || this.localPagination.size
								})) ||
							false
						// 后端数据records为null保存修复
						if (r.records == null) {
							r.records = []
						}
						// 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页
						if (r.records.length === 0 && this.showPagination && this.localPagination.current > 1) {
							this.localPagination.current--
							this.loadData()
							return
						}
						// 当情况满足时，表示数据不满足分页大小，关闭 table 分页功能
						try {
							/*
	if ((['auto', true].includes(this.showPagination) && r.total <= (r.pages * this.localPagination.size))) {
	this.localPagination.hideOnSinglePage = true
	}
	*/
							if (!this.showPagination) {
								this.localPagination.hideOnSinglePage = true
							}
						} catch (e) {
							this.localPagination = false
						}
						// 返回结果中的数组数据
						if (this.showPagination === false) {
							// 既然配置了不分页，那么我们这里接收到肯定是数组
							this.localDataSource = []
							if (r instanceof Array) {
								this.localDataSource = r
							}
						} else {
							this.localDataSource = r.records
						}
						this.localLoading = false
					})
				}
			},
			initTotalList(columns) {
				const totalList = []
				columns &&
					columns instanceof Array &&
					columns.forEach((column) => {
						if (column.needTotal) {
							totalList.push({
								...column,
								total: 0
							})
						}
					})
				return totalList
			},
			/**
			 * 用于更新已选中的列表数据 total 统计
			 * @param selectedRowKeys
			 * @param selectedRows
			 */
			updateSelect(selectedRowKeys, selectedRows) {
				this.selectedRows = selectedRows
				this.selectedRowKeys = selectedRowKeys
				const list = this.needTotalList
				this.needTotalList = list.map((item) => {
					return {
						...item,
						total: selectedRows.reduce((sum, val) => {
							const total = sum + parseInt(get(val, item.dataIndex))
							return isNaN(total) ? 0 : total
						}, 0)
					}
				})
			},
			/**
			 * 清空 table 已选中项
			 */
			clearSelected() {
				if (this.rowSelection) {
					this.rowSelection.onChange([], [])
					this.updateSelect([], [])
				}
			},
			/**
			 * 刷新并清空已选
			 */
			clearRefreshSelected(bool = false) {
				this.refresh(bool)
				this.clearSelected()
			},
			/**
			 * 处理交给 table 使用者去处理 clear 事件时，内部选中统计同时调用
			 * @param callback
			 * @returns {*}
			 */
			renderClear(callback) {
				if (this.selectedRowKeys.length <= 0) return null
				return (
					<a
						className="ml-6"
						onClick={() => {
							callback()
							this.clearSelected()
						}}>
						{' '}
						清空{' '}
					</a>
				)
			},
			renderAlert() {
				// 绘制统计列数据
				// eslint-disable-next-line no-unused-vars
				const needTotalItems = this.needTotalList.map((item) => {
					return (
						<span className="mr-3">
							{item.title} 总计 <a className="font-6">{!item.customRender ? item.total : item.customRender(item.total)}</a>
						</span>
					)
				})
				// 绘制 清空 按钮
				// eslint-disable-next-line no-unused-vars
				const clearItem = typeof this.alert.clear === 'boolean' && this.alert.clear ? this.renderClear(this.clearSelected) : typeof this.alert.clear === 'function' ? this.renderClear(this.alert.clear) : null
				// 绘制 alert 组件
				if (alert) {
					const message = (
						<div>
							<span className="mr-3">
								已选择: <a className="font-6">{this.selectedRows.length}</a>
							</span>
							{needTotalItems}
							{clearItem}
						</div>
					)
					return <a-alert showIcon class="mb-4" message={message} />
				}
			},
			columnChange(val) {
				this.columnsSetting = val
			},
			/**
			 * 渲染操作按钮
			 */
			renderOperatorButtons() {
				const buttons = this.operatorConfig
					.map((config, index) => {
						// 检查按钮是否可见
						const isVisible = typeof config.visible === 'function' ? config.visible() : config.visible
						if (isVisible === false) return null

						// 检查按钮是否禁用
						const isDisabled = typeof config.disabled === 'function' ? config.disabled() : config.disabled

						if (config.type === 'popconfirm') {
							return (
								<a-popconfirm key={index} title={config.confirmTitle || '确认执行此操作？'} ok-text={config.okText || '确定'} cancel-text={config.cancelText || '取消'} onConfirm={config.onClick}>
									<a-button type="link" danger={config.danger} disabled={isDisabled} style={{ padding: '4px 8px' }}>
										{config.icon && (typeof config.icon === 'string' ? <i class={config.icon} style={{ marginRight: '4px' }} /> : <span style={{ marginRight: '4px' }}>{config.icon}</span>)}
										{config.text}
									</a-button>
								</a-popconfirm>
							)
						} else if (config.type === 'upload') {


							return (
								<a-upload
											key={index}
											ref={config.ref || 'upload'}
											class="upload-demo"
											accept={(config.uploadProps && config.uploadProps.accept) || config.accept}
											headers={(config.uploadProps && config.uploadProps.headers) || config.headers}
											show-upload-list={(config.uploadProps && config.uploadProps.showUploadList) || false}
											action={(config.uploadProps && config.uploadProps.action) || (config.uploadProps && config.uploadProps.uploadUrl) || config.action || config.uploadUrl}
											show-file-list={(config.uploadProps && config.uploadProps.showFileList) || false}
											auto-upload={(config.uploadProps && config.uploadProps.autoUpload) || true}
											multiple={(config.uploadProps && config.uploadProps.multiple) || false}
											on-success={(config.uploadProps && config.uploadProps.onSuccess) || config.onSuccess}
											on-error={(config.uploadProps && config.uploadProps.onError) || config.onError}
											before-upload={(config.uploadProps && config.uploadProps.beforeUpload) || (() => true)}
											style={{ display: 'inline-block' }}
										>
									<a-button slot="trigger" type="link" disabled={isDisabled} loading={config.loading || false} style={{ padding: '4px 8px' }}>
										{config.icon && (typeof config.icon === 'string' ? <i class={config.icon} style={{ marginRight: '4px' }} /> : <span style={{ marginRight: '4px' }}>{config.icon}</span>)}
										{config.text}
									</a-button>
								</a-upload>
							)
						} else {
							return (
								<a-button key={index} type="link" danger={config.danger} disabled={isDisabled} onClick={config.onClick} style={{ padding: '4px 8px' }}>
									{config.icon && (typeof config.icon === 'string' ? <i class={config.icon} style={{ marginRight: '4px' }} /> : <span style={{ marginRight: '4px' }}>{config.icon}</span>)}
									{config.text}
								</a-button>
							)
						}
					})
					.filter(Boolean)

				// 使用divider分隔按钮
				const buttonsWithDividers = []
				buttons.forEach((button, index) => {
					buttonsWithDividers.push(button)
					if (index < buttons.length - 1) {
						buttonsWithDividers.push(<a-divider key={`divider-${index}`} type="vertical" />)
					}
				})

				return (
					<div class="operator-buttons" style={{ display: 'flex', alignItems: 'center' }}>
						{buttonsWithDividers}
					</div>
				)
			},
			handleResizeColumn(w, col) {
				col.width = w
			},
			renderHeader() {
				let tools = [
					{
						name: 'refresh',
						icon: <i class="fa fa-refresh ml-4" />,
						title: '刷新',
						onClick: () => {
							this.refresh()
						}
					},
					{
						name: 'height',
						icon: <i class="fa fa-arrows-v" />,
						title: '密度',
						isDropdown: true,
						menu: () => {
							const onClick = ({ key }) => {
								this.customSize = key
							}
							return (
								<a-menu onClick={onClick} selectable selectedKeys={[this.customSize]}>
									<a-menu-item key="default">默认</a-menu-item>
									<a-menu-item key="middle">中等</a-menu-item>
									<a-menu-item key="small">紧凑</a-menu-item>
								</a-menu>
							)
						},
						onClick: () => {}
					},
					{
						name: 'columnSetting',
						icon: <i class="fa fa-cog" />,
						title: '列设置',
						isPopover: true,
						visible: false,
						menu: () => {
							return <columnSetting columns={this.columns} onColumnChange={this.columnChange} />
						},
						onClick: () => {}
					}
				]
				if (this.extraTool.length) {
					tools = tools.concat(this.extraTool)
				}
				// 斑马纹
				const changeRowClass = (value) => {
					const val = value.target.checked
					this.localSettings.rowClassNameSwitch = val
					const evenClass = val ? (_record, index) => (index % 2 === 1 ? 'table-striped' : null) : this.rowClassName
					this.localSettings.rowClassName = evenClass
				}
				const setShowOperator = () => {
					if (this.showOperator === true) {
						this.showOperator = false
					} else {
						this.showOperator = true
					}
				}
				return (
					<div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap', width: '100%' }}>
						{this.showOperator && (
							<>
								{this.$slots.pageInfo && this.$slots.pageInfo()}
								{this.$slots.operator && this.$slots.operator()}
								{this.operatorConfig.length > 0 && this.renderOperatorButtons()}
							</>
						)}
						<div style={{ display: 'flex', alignItems: 'center', gap: '8px', justifyContent: 'space-between', margin: '0 0 0 auto' }}>
							<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
								{this.toolConfig.striped ? (
									<div style={{ display: 'flex', alignItems: 'center' }}>
										<a-checkbox checked={this.localSettings.rowClassNameSwitch} onChange={changeRowClass}>
											斑马纹
										</a-checkbox>
									</div>
								) : null}
							</div>
							<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
								{tools.map((tool, index) => {
									if (!this.toolConfig[tool.name]) {
										return null
									}
									const toolElement = (
										<div style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }} onClick={tool.onClick}>
											{tool.icon}
											<span style={{ marginLeft: '4px' }}>{tool.title}</span>
										</div>
									)
									let wrappedElement
									if (tool.isPopover) {
										wrappedElement = (
											<a-popover trigger={'click'} placement="topLeft" overlayClassName="s-table-column-settings" arrow-point-at-center content={tool.menu()}>
												{toolElement}
											</a-popover>
										)
									} else if (tool.isDropdown) {
										wrappedElement = (
											<a-dropdown trigger={['click']} overlay={tool.menu()}>
												{toolElement}
											</a-dropdown>
										)
									} else {
										wrappedElement = toolElement
									}
									return (
										<>
											{wrappedElement}
											{index < tools.filter((t) => this.toolConfig[t.name]).length - 1 && <a-divider type="vertical" />}
										</>
									)
								})}
							</div>
						</div>
					</div>
				)
			}
		},
		render() {
			let props = {}
			const localKeys = Object.keys(this.$data)
			const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show && typeof this.rowSelection.selectedRowKeys !== 'undefined') || this.alert
			Object.keys(tableProps()).forEach((k) => {
				const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`
				if (localKeys.includes(localKey)) {
					props[k] = this[localKey]
					return props[k]
				}
				if (k === 'rowSelection') {
					if (showAlert && this.rowSelection) {
						// 如果需要使用alert，则重新绑定 rowSelection 事件
						props[k] = {
							...this.rowSelection,
							selectedRows: this.selectedRows,
							selectedRowKeys: this.selectedRowKeys,
							onChange: (selectedRowKeys, selectedRows) => {
								this.updateSelect(selectedRowKeys, selectedRows)
								typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)
							}
						}
						return props[k]
					} else if (!showAlert && this.rowSelection) {
						props[k] = {
							...this.rowSelection,
							selectedRows: this.selectedRows,
							selectedRowKeys: this.selectedRowKeys,
							onChange: (selectedRowKeys, selectedRows) => {
								this.updateSelect(selectedRowKeys, selectedRows)
								typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)
							}
						}
						return props[k]
					} else if (!this.rowSelection) {
						// 如果没打算开启 rowSelection 则清空默认的选择项
						props[k] = null
						return props[k]
					}
				}
				this[k] && (props[k] = this[k])
				// 此处配置表格大小与要显示的列
				props = {
					...props,
					size: this.customSize, // 注意这个size是a-table组件需要的，这里不能跟别的地方成为compSize
					columns: this.columnsSetting.filter((value) => value.checked === undefined || value.checked)
				}
				return props[k]
			})
			const table = (
				<a-table
					{...props}
					{...this.localSettings}
					v-slots={this.$slots}
					onChange={this.loadData}
					onExpand={(expanded, record) => {
						this.$emit('expand', expanded, record)
					}}
					onResizeColumn={this.handleResizeColumn}
				/>
			)
			let result = (
				<div className="table-wrapper">
					{this.renderHeader()}
					{showAlert ? this.renderAlert() : null}
					{table}
				</div>
			)
			return result
		}
	}
</script>
